﻿using System;
using System.Collections.Generic;
using System.Linq;
using Model.Entity;
using Ones.Dal.Infrastructure;
using Ones.Dal.Repository.Interfaces;

namespace Ones.Dal.Repository.Impl
{
    public class EmployeeDao : AbstractDao<Employee>, IEmployeeDao
    {
        public override bool
        create(Employee emp)
        {
            try
            {
                emp.empId = this.createPrefixId();

                _ctx.Employees.InsertOnSubmit(emp);
                _ctx.SubmitChanges();
                return true;
            }
            catch (Exception)
            {
                return false;
            }
        }

        public override bool
        update(Employee emp)
        {
            try
            {
                var curr = getById(emp.empId);

                curr.userId = emp.userId;
                curr.empFirstName = emp.empFirstName;
                curr.empLastName = emp.empLastName;
                curr.empGender = emp.empGender;
                curr.empDateModify = emp.empDateModify;
                curr.empDateJoin = emp.empDateJoin;
                curr.empDateLeave = emp.empDateLeave;

                _ctx.SubmitChanges();
                return true;
            }
            catch (Exception)
            {
                return false;
            }
        }

        public string
        createPrefixId()
        {
            string currMaxId = getAll().Max(i => i.empId);
            string prefixPart = "emp";
            int nDigits = 6;

            AutoId autoid = new AutoId();

            return autoid.tryCreatePrefixId(currMaxId, prefixPart, nDigits);
        }

        public override Employee
        getById(object id)
        {
            return getSingle(i => i.empId.Equals((string)id));
        }

        public Employee
        getByUser(Guid userId)
        {
            return getSingle(i => i.userId == userId);
        }

        public List<Employee>
        getByName(string empName)
        {
            try
            {
                return getMultiple(i => i.empFirstName.Contains(empName) ||
                                        i.empLastName.Contains(empName));
            }
            catch (Exception)
            {
                return null;
            }
        }

        public List<Employee>
        getByGender(bool isMale)
        {
            try
            {
                return getMultiple(i => i.empGender == isMale);
            }
            catch (Exception)
            {
                return null;
            }
        }

        public List<Employee>
        getByJoinedDate(DateTime empDateJoin)
        {
            try
            {
                return getMultiple(i => i.empDateJoin.Equals(empDateJoin));
            }
            catch (Exception)
            {
                return null;
            }
        }

        public List<Employee>
        getByJoinedDate(int yyyy, int mm, int dd)
        {
            try
            {
                return getMultiple(i => i.empDateJoin.Year == yyyy &&
                                        i.empDateJoin.Month == mm &&
                                        i.empDateJoin.Day == dd);
            }
            catch (Exception)
            {
                return null;
            }
        }

        ////NOTE: question for Hao`
        public bool
        addAccountToEmployee(string empId, Guid userId)
        {
            try
            {
                var q = (from e in _ctx.Employees
                         where e.empId == empId
                         select e).First();
                q.userId = userId;
                _ctx.SubmitChanges();
                return true;
            }
            catch (Exception)
            {
                return false;
            }
        }

        public PagingObject<Employee>
        getAll(int page)
        {
            try
            {
                var q = from e in _ctx.Employees
                        select e;

                List<Employee> list = new List<Employee>();
                int numberOfObjectsPerPage = 10;
                var queryResultPage = q.Skip(numberOfObjectsPerPage * (page - 1)).Take(numberOfObjectsPerPage);
                PagingObject<Employee> obj = new PagingObject<Employee>();
                obj.Data = queryResultPage.ToList();
                obj.TotalPage = q.Count() / numberOfObjectsPerPage;
                if (q.Count() % numberOfObjectsPerPage > 0)
                    obj.TotalPage = obj.TotalPage + 1;
                return obj;
            }
            catch (Exception)
            {
                return null;
            }
        }

        ////NOTE: question for Hao`
        public PagingObject<Employee>
        getAllWithoutUserId(int page)
        {
            try
            {
                var q = from e in _ctx.Employees
                        where e.userId.Value == null
                        select e;

                List<Employee> list = new List<Employee>();
                int numberOfObjectsPerPage = 10;
                var queryResultPage = q.Skip(numberOfObjectsPerPage * (page - 1)).Take(numberOfObjectsPerPage);
                
                PagingObject<Employee> obj = new PagingObject<Employee>();
                obj.Data = queryResultPage.ToList();
                obj.TotalPage = q.Count() / numberOfObjectsPerPage;
                if (q.Count() % numberOfObjectsPerPage > 0)
                {
                    obj.TotalPage = obj.TotalPage + 1;
                }

                return obj;
            }
            catch (Exception)
            {
                return null;
            }
        }
    }

    #region IEmployeeDao

    public interface IEmployeeDao : IDao<Employee>
    {
        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        String createPrefixId();

        /// <summary>
        /// Select employee info based on username
        /// </summary>
        /// <param name="userName"></param>
        /// <returns></returns>
        //Employee getByUser(String userName);

        /// <summary>
        /// Select employee info based on userid
        /// </summary>
        /// <param name="userId"></param>
        /// <returns></returns>
        Employee getByUser(Guid userId);

        /// <summary>
        /// Select employee info based on Name
        /// </summary>
        /// <param name="empName"></param>
        /// <returns></returns>
        List<Employee> getByName(String empName);

        /// <summary>
        /// Select employee info based on gender
        /// </summary>
        /// <param name="isMale"></param>
        /// <returns></returns>
        List<Employee> getByGender(Boolean isMale);

        /// <summary>
        /// Select employee info based on joined date
        /// </summary>
        /// <param name="empJoinedDate"></param>
        /// <returns></returns>
        List<Employee> getByJoinedDate(DateTime empJoinedDate);

        /// <summary>
        /// 
        /// </summary>
        /// <param name="yyyy"></param>
        /// <param name="mm"></param>
        /// <param name="dd"></param>
        /// <returns></returns>
        List<Employee> getByJoinedDate(int yyyy, int mm, int dd);

        /// <summary>
        /// 
        /// </summary>
        /// <param name="empId"></param>
        /// <param name="userId"></param>
        /// <returns></returns>
        Boolean addAccountToEmployee(String empId, Guid userId);

        /// <summary>
        /// 
        /// </summary>
        /// <param name="page"></param>
        /// <returns></returns>
        PagingObject<Employee> getAll(int page);
        
        /// <summary>
        /// 
        /// </summary>
        /// <param name="page"></param>
        /// <returns></returns>
        PagingObject<Employee> getAllWithoutUserId(int page);
    }
    #endregion
}